#pragma once

//
// Request completion callback
//
typedef struct _VIOFS_INKERNEL_REQUEST* PVIOFS_INKERNEL_REQUEST;

typedef
VOID
VIRTIOFS_REQUEST_COMPLETE_FUNC(
    PVIOFS_INKERNEL_REQUEST Request,
    UINT64                  BytesReturned // Bytes returned in FuseOutHeader + Request::OutBuf
);

typedef VIRTIOFS_REQUEST_COMPLETE_FUNC* PVIRTIOFS_REQUEST_COMPLETE_FUNC;

//
// Must match the struct VirtIOBufferDescriptor
//
typedef struct _VIOFS_SG
{
    PHYSICAL_ADDRESS PhyAddr;
    ULONG            Length;
} VIOFS_SG, *PVIOFS_SG;

//
// Request for fuse-operation from other kernel driver
//
typedef struct _VIOFS_INKERNEL_REQUEST
{
    PVOID       CallerContext; // Context of the caller

    PVIRTIOFS_REQUEST_COMPLETE_FUNC CompleteCallback;

    ULONG       FuseOpcode;
    ULONG       pad; // keep alignment to UINT64

    ULONG       InputSgCount;
    ULONG       OutputSgCount;

    // Array of SGs. First InputSgCount entries describes input buffer.
    // The next OutputSgCount - output buffer
    PVIOFS_SG   Sg;
} VIOFS_INKERNEL_REQUEST, *PVIOFS_INKERNEL_REQUEST;

typedef
NTSTATUS
VIRTIOFS_INKERNEL_FUSE_REQUEST_ROUTINE_FUNC(
    IN  PVOID                    ViofsContext,
    IN  PVIOFS_INKERNEL_REQUEST  ViofsRequest
);
typedef VIRTIOFS_INKERNEL_FUSE_REQUEST_ROUTINE_FUNC* PVIRTIOFS_INKERNEL_FUSE_REQUEST_ROUTINE_FUNC;

typedef
BOOLEAN
VIRTIOFS_INKERNEL_FUSE_CANCEL_REQUEST_FUNC(
    IN  PVOID                    ViofsContext,
    IN  PVIOFS_INKERNEL_REQUEST  ViofsRequest
);
typedef VIRTIOFS_INKERNEL_FUSE_CANCEL_REQUEST_FUNC* PVIRTIOFS_INKERNEL_FUSE_CANCEL_REQUEST_FUNC;

typedef
VOID
VIRTIOFS_INKERNEL_RESET_FUNC(
    IN  PVOID                    ViofsContext
);
typedef VIRTIOFS_INKERNEL_RESET_FUNC* PVIRTIOFS_INKERNEL_RESET_FUNC;

#define VIRTFS_INKERNEL_API_VERSION             0x3

//
// return data of IOCTL_VIRTFS_GET_INKERNEL_API
//
typedef struct _VIRTIOFS_INKERNEL_FUSE_REQUEST_ROUTINE
{
    UINT64                                        ApiVersion;
    PVOID                                         ViofsContext;
    PVIRTIOFS_INKERNEL_FUSE_REQUEST_ROUTINE_FUNC  Func;
    PVIRTIOFS_INKERNEL_FUSE_CANCEL_REQUEST_FUNC   CancelFunc;
    PVIRTIOFS_INKERNEL_RESET_FUNC                 ResetFunc;
} VIRTIOFS_INKERNEL_FUSE_REQUEST_ROUTINE;
